package com.star.system.service.impl;

import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.star.common.utils.TreeUtil;
import com.star.system.config.LocalAuthenticationService;
import com.star.system.dto.MenuSaveDTO;
import com.star.system.dto.MenuUpdateDTO;
import com.star.system.entity.Menu;
import com.star.system.entity.User;
import com.star.system.enums.MenuType;
import com.star.system.mapper.MenuMapper;
import com.star.system.service.MenuService;
import com.star.system.service.RoleMenuService;
import com.star.system.struct.MenuStruct;
import com.star.system.vo.MenuRoleTreeVO;
import com.star.system.vo.MenuTreeVO;
import com.star.system.vo.MenuUserTreeVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 菜单 服务实现类
 *
 * @author yangzj
 */
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    @Autowired
    private RoleMenuService roleMenuService;
    @Autowired
    private LocalAuthenticationService localAuthenticationService;
    /**
     * 树根
     */
    public static final String TREE_ROOT = "0";

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void save(MenuSaveDTO dto) {
        this.save(MenuStruct.INSTANCE.to(dto));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void update(MenuUpdateDTO dto) {
        Long id = dto.getId();
        Assert.notNull(this.getById(id), "菜单不存在");
        this.update(MenuStruct.INSTANCE.to(dto), Wrappers.<Menu>lambdaUpdate()
                .eq(Menu::getId, id)
                .set(Menu::getName, dto.getName())
                .set(Menu::getPath, dto.getPath())
                .set(Menu::getRedirect, dto.getRedirect())
                .set(Menu::getIcon, dto.getIcon())
                .set(Menu::getAuthorities, dto.getAuthorities()));
        // 更新用户权限
        baseMapper.listUserByIds(Collections.singletonList(id)).forEach(localAuthenticationService::refresh);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteByIds(List<Long> ids) {
        List<User> users = baseMapper.listUserByIds(ids);
        this.removeByIds(ids);
        roleMenuService.deleteByMenuIds(ids);
        // 更新小程序用户权限
        users.forEach(localAuthenticationService::refresh);
    }

    @Override
    public List<MenuTreeVO> tree() {
        return TreeUtil.build(baseMapper.listAll(null));
    }

    @Override
    public List<MenuRoleTreeVO> treeAll() {
        return TreeUtil.build(baseMapper.treeAll(), TREE_ROOT);
    }

    @Override
    public List<MenuRoleTreeVO> treeRole(Long roleId) {
        return TreeUtil.build(baseMapper.treeRole(roleId), TREE_ROOT);
    }

    @Override
    public List<MenuUserTreeVO> treeUser(Long userId, boolean admin) {
        List<MenuTreeVO> list = admin ? baseMapper.listAll(MenuType.MENU.getCode()) : baseMapper.listByUserId(userId);
        return TreeUtil.build(list.stream()
                .map(c -> MenuStruct.INSTANCE.to(c).setMeta(MenuStruct.INSTANCE.toMeta(c)))
                .collect(Collectors.toList()), TREE_ROOT);
    }
}
